import Cesium, { Matrix4 } from '../Ces/Cesium'
import Util from '../Core/Util'
import WeDisplay from './WeDisplay'
import WeGeometryUtil from './WeGeometryUtil'
import WeGridMovableCubeShaders from './WeGridMovableCubeShaders'
import { optionsToUniforms, WeGridMovableOptions } from './WeGridMovableStyle'
import WeGridMovableUpdatePosition from './WeGridMovableUpdatePosition'
import WeUniform from './WeUniform'

class WeGridMovableCube {
  show: boolean = true
  dirty: boolean = true
  gridMovableUpdatePosition: WeGridMovableUpdatePosition
  weUniform: WeUniform
  display: WeDisplay
  command//: Cesium.DrawCommand
  modelMatrix: Matrix4
  _freezing: boolean = false
  constructor(options: WeGridMovableOptions, display: WeDisplay) {
     this.weUniform = optionsToUniforms(options)

    const rectangle = display.imageryLayer.rectangle
    const meterSize = Util.computeRectangleMeter(rectangle)
    const meterWidth = meterSize.width
    const meterHeight = meterSize.height
    const useRTCenter = Math.max(meterWidth, meterHeight) < 10000
    const position = new Cesium.Cartesian3()
    if (useRTCenter) {
      Cesium.Cartesian3.fromRadians(
        rectangle.west + rectangle.width * 0.5,
        rectangle.south + rectangle.height * 0.5,
        0.0,
        Cesium.Ellipsoid.default,
        position,
      )
      this.modelMatrix = Util.getEnuModelMatrix(position, new Cesium.Matrix4())
      this.weUniform.Properties.useRTCenter = 1.0
      this.weUniform.Properties.meterWidth = meterWidth
      this.weUniform.Properties.meterHeight = meterHeight
    }

    this.weUniform.Properties.viewExtent = rectangle
    this.display = display
  }

  set freezing(value) {
    this._freezing = value
  }

  set showArrow(value) {
    this.weUniform.Properties.particleStyle = value
  }

  set viewExtent(value) {
    const rectangle = value
    const meterSize = Util.computeRectangleMeter(value)
    const meterWidth = meterSize.width
    const meterHeight = meterSize.height
    const useRTCenter = Math.max(meterWidth, meterHeight) < 10000
    this.weUniform.Properties.useRTCenter = useRTCenter ? 1.0 : 0.0
    this.weUniform.Properties.meterWidth = meterWidth
    this.weUniform.Properties.meterHeight = meterHeight
    this.weUniform.Properties.viewExtent = value
    if (useRTCenter) {
      const position = new Cesium.Cartesian3()
      Cesium.Cartesian3.fromRadians(
        rectangle.west + rectangle.width * 0.5,
        rectangle.south + rectangle.height * 0.5,
        0.0, Cesium.Ellipsoid.default, position)
      this.modelMatrix = Util.getEnuModelMatrix(position, new Cesium.Matrix4())
    } else {
      this.modelMatrix = null
    }
  }

  rebuild(context) {
    const { display, weUniform } = this
    this.gridMovableUpdatePosition = this.gridMovableUpdatePosition && this.gridMovableUpdatePosition.destroy()
    this.gridMovableUpdatePosition = new WeGridMovableUpdatePosition({
      display: this.display,
      weUniform,
      context,
    })

    const { vertexArray, attributeLocations } = WeGeometryUtil.createCubeGeometry(
      context, weUniform.Properties.numLon, weUniform.Properties.numLat, 6
    )

    const uniformMap = {
      u_particlesTexture0: () => this.gridMovableUpdatePosition.framebuffers[0].getColorTexture(0),
    }

    weUniform.setupUniformMap(uniformMap)
    display.setupUniformMap(uniformMap)

    const uniformSource = weUniform.getSource();
    const baseFragmentSource = display.getFragmentShaderSource(true, true, true)

    const vertexShaderSource = `
    ${uniformSource}
    ${baseFragmentSource}
    ${WeGridMovableCubeShaders.vertexShaderSource}
    `

    const fragmentShaderSource = `
    ${uniformSource}
    ${baseFragmentSource}
    ${WeGridMovableCubeShaders.fragmentShaderSource}
    `

    const shaderProgram = Cesium.ShaderProgram.fromCache({
      context,
      vertexShaderSource,
      fragmentShaderSource,
      attributeLocations,
    })

    const renderState = Cesium.RenderState.fromCache({
      cull: {
        enabled: true,
        face: Cesium.CullFace.BACK,
      },
      depthTest: {
        enabled: true,
      },
      blending: Cesium.BlendingState.ALPHA_BLEND,
    })

    this.command = new Cesium.DrawCommand({
      vertexArray,
      shaderProgram,
      uniformMap,
      renderState,
      pass: Cesium.Pass.TRANSLUCENT,
      modelMatrix: this.modelMatrix,
    })
  }

  update(frameState) {
    if (!this.show || !frameState.passes.render) return
    if (this.dirty) {
      this.dirty = false
      this.rebuild(frameState.context)
    }
    this.gridMovableUpdatePosition.update(frameState)
    frameState.commandList.push(this.command)
  }
  destroy() {
    this.command = this.command && this.command.shaderProgram && this.command.shaderProgram.destroy()
    this.gridMovableUpdatePosition = this.gridMovableUpdatePosition && this.gridMovableUpdatePosition.destroy()
    return Cesium.destroyObject(this)
  }
  isDestroyed() {
    return false
  }
}

export default WeGridMovableCube
